/*
 * MIT License
 *
 * Copyright (c) 2021 cao.yong<cymsn81@126.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.cy.websocket.stomp;

import org.cy.websocket.stomp.events.OnConnectedEvent;
import org.cy.websocket.stomp.events.OnDisconnectedEvent;
import org.cy.websocket.stomp.events.OnErrorEvent;
import org.cy.websocket.stomp.util.StringKit;

/**
 * 客户端的构造器
 *
 * created in 2021/5/14
 *
 * @author cao.yong
 */
public class StompClientBuilder {
    /**
     * 默认重连间隔设置
     */
    private static final long RECONNECT_DELAY = 5000;

    private final Heartbeat heartbeat = new Heartbeat();
    private String url;
    private boolean retry = true;
    private StompHeaders connectHeaders;
    private StompHeaders disconnectHeaders;
    private OnConnectedEvent onConnectedEvent = null;
    private OnDisconnectedEvent onDisconnectedEvent = null;
    private OnErrorEvent onErrorEvent = null;

    /**
     * 设置 STOMP 服务地址
     * @param url 服务地址，必须设置
     * @return 客户端构造器
     */
    public StompClientBuilder url(String url) {
        this.url = url;
        return this;
    }

    /**
     * 心跳配置
     * @param incoming 接收来自服务器的心跳消息间隔， 0 关闭
     * @param outgoing 主动向服务器发送心跳消息间隔， 0 关闭
     * @return 客户端构造器
     */
    public StompClientBuilder heartbeat(long incoming, long outgoing) {
        heartbeat.setIncoming(incoming);
        heartbeat.setOutgoing(outgoing);
        return this;
    }

    /**
     * 设置服务器断开后，是否尝试重连
     * @param retry 默认为 true, 不进行重连设置为 false.
     * @return 客户端构造器
     */
    public StompClientBuilder isRetry(boolean retry) {
        this.retry = retry;
        return this;
    }

    /**
     * 连接时，STOMP 协议头配置
     * @param headers {@link StompHeaders} STOMP 协议头
     * @return 客户端构造器
     */
    public StompClientBuilder connectHeaders(StompHeaders headers) {
        this.connectHeaders = headers;
        return this;
    }

    /**
     * 断开时，STOMP 协议头配置
     * @param headers {@link StompHeaders} STOMP 协议头
     * @return 客户端构造器
     */
    public StompClientBuilder disconnectHeaders(StompHeaders headers) {
        this.disconnectHeaders = headers;
        return this;
    }

    /**
     * 连接成功后的回调事件配置
     * @param event 回调事件
     * @return 客户端构造器
     */
    public StompClientBuilder onConnected(OnConnectedEvent event) {
        this.onConnectedEvent = event;
        return this;
    }

    /**
     * 断开成功后的回调事件配置
     * @param event 回调事件
     * @return 客户端构造器
     */
    public StompClientBuilder onDisconnected(OnDisconnectedEvent event) {
        this.onDisconnectedEvent = event;
        return this;
    }

    /**
     * 发生错误后的回调事件配置
     * @param event 回调事件
     * @return 客户端构造器
     */
    public StompClientBuilder onError(OnErrorEvent event) {
        this.onErrorEvent = event;
        return this;
    }

    /**
     * 构建 STOMP 客户端实例
     * @return 客户端实例
     */
    public StompClient build() {
        StompClient client = new StompClient();
        if (StringKit.isEmpty(url)) {
            throw new IllegalArgumentException("Stomp url must be not null");
        }
        client.setBrokerUrl(url);
        client.setHeartbeat(heartbeat.getIncoming(), heartbeat.getOutgoing());
        if (retry) {
            client.setReconnectDelay(RECONNECT_DELAY);
        } else {
            client.setReconnectDelay(0);
        }

        if (null == connectHeaders) {
            connectHeaders = new StompHeaders();
        }
        client.setConnectHeaders(connectHeaders);

        if (null == disconnectHeaders) {
            disconnectHeaders = new StompHeaders();
        }
        client.setDisconnectHeaders(disconnectHeaders);

        if (null == onConnectedEvent) {
            onConnectedEvent = message -> {};
        }
        client.setOnConnected(onConnectedEvent);

        if (null == onDisconnectedEvent) {
            onDisconnectedEvent = () -> {};
        }
        client.setOnDisconnected(onDisconnectedEvent);

        if (null == onErrorEvent) {
            onErrorEvent = ex -> {};
        }
        client.setOnError(onErrorEvent);
        return client;
    }
}
